// hooks/useRequest/debounceThrottle.ts

/**
 * 防抖函数
 * @param fn 需要防抖的函数
 * @param wait 等待时间（毫秒）
 * @returns 防抖后的函数
 */
export const debounce = <T extends (...args: any[]) => any>(
    fn: T,
    wait: number
): ((...args: Parameters<T>) => Promise<ReturnType<T>>) => {
    let timer: ReturnType<typeof setTimeout> | null = null;
    let resolveList: Array<(value: ReturnType<T> | PromiseLike<ReturnType<T>>) => void> = [];
    let rejectList: Array<(reason?: any) => void> = [];

    return function (this: any, ...args: Parameters<T>): Promise<ReturnType<T>> {
        return new Promise<ReturnType<T>>((resolve, reject) => {
            resolveList.push(resolve);
            rejectList.push(reject);

            if (timer) {
                clearTimeout(timer);
            }

            timer = setTimeout(() => {
                const currentResolveList = [...resolveList];
                const currentRejectList = [...rejectList];

                resolveList = [];
                rejectList = [];
                timer = null;

                try {
                    const result = fn.apply(this, args);
                    if (result instanceof Promise) {
                        result
                            .then(res => {
                                currentResolveList.forEach(resolveFn => resolveFn(res));
                            })
                            .catch(err => {
                                currentRejectList.forEach(rejectFn => rejectFn(err));
                            });
                    } else {
                        currentResolveList.forEach(resolveFn => resolveFn(result));
                    }
                } catch (error) {
                    currentRejectList.forEach(rejectFn => rejectFn(error));
                }
            }, wait);
        });
    };
};

/**
 * 节流函数
 * @param fn 需要节流的函数
 * @param wait 等待时间（毫秒）
 * @returns 节流后的函数
 */
export const throttle = <T extends (...args: any[]) => any>(
    fn: T,
    wait: number
): ((...args: Parameters<T>) => Promise<ReturnType<T>>) => {
    let lastCallTime = 0;
    let timer: ReturnType<typeof setTimeout> | null = null;
    let pendingPromise: Promise<ReturnType<T>> | null = null;
    let lastArgs: Parameters<T> | null = null;
    let context: any = null;

    // 创建一个执行函数
    const execute = (): Promise<ReturnType<T>> => {
        if (!lastArgs) {
            return Promise.reject(new Error('No arguments provided'));
        }

        const args = lastArgs;
        lastArgs = null;

        try {
            const result = fn.apply(context, args);
            if (result instanceof Promise) {
                return result;
            }
            return Promise.resolve(result);
        } catch (error) {
            return Promise.reject(error);
        }
    };

    return function (this: any, ...args: Parameters<T>): Promise<ReturnType<T>> {
        context = this;
        lastArgs = args;

        const now = Date.now();
        const remaining = wait - (now - lastCallTime);

        // 如果已经有一个等待中的请求，直接返回
        if (pendingPromise) {
            return pendingPromise;
        }

        // 如果是第一次调用或者已经过了节流时间
        if (remaining <= 0) {
            lastCallTime = now;
            pendingPromise = execute();

            pendingPromise.finally(() => {
                pendingPromise = null;
            });

            return pendingPromise;
        }

        // 否则，创建一个新的Promise并在剩余时间后执行
        return new Promise<ReturnType<T>>((resolve, reject) => {
            timer = setTimeout(() => {
                lastCallTime = Date.now();
                timer = null;

                const promise = execute();
                pendingPromise = promise;

                promise
                    .then(resolve)
                    .catch(reject)
                    .finally(() => {
                        pendingPromise = null;
                    });
            }, remaining);
        });
    };
};

/**
 * 创建防抖请求函数
 * @param requestFn 请求函数
 * @param wait 等待时间（毫秒）
 * @returns 防抖后的请求函数
 */
export const createDebouncedRequest = <T>(
    requestFn: (params?: any) => Promise<T>,
    wait: number
) => {
    return debounce<(params?: any) => Promise<T>>(requestFn, wait);
};

/**
 * 创建节流请求函数
 * @param requestFn 请求函数
 * @param wait 等待时间（毫秒）
 * @returns 节流后的请求函数
 */
export const createThrottledRequest = <T>(
    requestFn: (params?: any) => Promise<T>,
    wait: number
) => {
    return throttle<(params?: any) => Promise<T>>(requestFn, wait);
}; 